# -*- coding: utf-8 -*-
# &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
# odoo16
# QQ:35350428
# 邮件:35350428@qq.com
# 手机：13584935775
# 作者：'Amos'
# 公司网址： www.xodoo.cn
# Copyright 昆山一百计算机有限公司
# 日期：2023-09-16
# &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

import time
import hashlib
import datetime
import uuid
from odoo import _, api, fields, models, http
from odoo.exceptions import ValidationError
from odoo import api, fields, models, tools, SUPERUSER_ID, _
from odoo.exceptions import AccessError, UserError, ValidationError

class workflow(models.Model):
    """
    工作流
    """
    _name = "workflow"
    _description = "工作流"
    _log_access = False
    _order = 'id desc'

    def _get_default_uuid(self):
        return str(uuid.uuid4())

    name = fields.Char(string='流程名称')
    number = fields.Char(string='流程编号', default=_get_default_uuid)
    user_id = fields.Many2one('res.users', string='指定用户', index=True)
    department_id = fields.Many2one('hr.department', string='指定部门', index=True)
    company_id = fields.Many2one('res.company', string='指定公司', index=True)
    res_model = fields.Char(string='对象名称', )
    res_id = fields.Char(string='记录ID', )
    model_id = fields.Many2one('ir.model', string='对象')
    model = fields.Char(related='model_id.model', string='对象实体', store=True)

    active = fields.Boolean(default=True, string='是否有效')
    sequence = fields.Integer(string='排序', default=10)
    note = fields.Text('备注')

    create_uid = fields.Many2one('res.users', string='创建人', index=True, default=lambda self: self.env.user)
    create_date = fields.Datetime(string='创建日期', readonly=True, default=fields.Datetime.now)

    label = fields.Char(string='节点标签', store=True)
    x = fields.Integer(string='节点位置X', default=0)
    y = fields.Integer(string='节点位置Y', default=0)
    width = fields.Integer(string='节点宽', default=1)
    height = fields.Integer(string='节点高', default=1)
    angle = fields.Integer(string='节点旋转角度', default=0)
    shape = fields.Selection([
        ('html', 'html'),
        ('rect', 'rect'),
        ('ellipse', 'ellipse'),
    ], string='属性', default='html')
    html = fields.Html()
    node_ids = fields.One2many('workflow.node', 'workflow_id', string='工作流结点', copy=True, auto_join=True)
    codeing = fields.Text('每次调用时执行Python 代码')

    # 统一添加前端传过来的所有图表信息，可以更好的映射相关信息
    str_workflow = fields.Text(string="图形化字符串代码", default = "") 

    @api.onchange('model_id')
    def onchange_model_id(self):
        values = {}
        if self.model_id:
            values['name'] = self.model_id.name
            values['res_model'] = self.model_id.model
            values['res_id'] = self.model_id.id
        self.update(values)

    def edit_workflow(self):
        workflow_id = self.id
        url = "/workflow?model=amos.demo&ttype=read&mode=edit&workflow_id=%s" % workflow_id 
        return {
            'type': 'ir.actions.act_url',
            'url': url,
        }


    def button_state(self):
        """
        计算出对象状态下有多少个状态，并安顺序生成好
        用户再配置好状态间的关系
        :return:
        """
        try:
            selection = self.pool.models[self.model_id.model].state.selection
            self.node_ids.unlink()
        except Exception as r:
            raise UserError('警告：不存在 state %s' % r)

        sequence = 1
        ref = False
        for line in selection:
            values = {
                'sequence': sequence,
                'workflow_id': self.id,
                'name': '审批',
                'state_form': line[0],
                'refuse': selection[0][0],
            }
            if len(selection) == sequence:
                values['state_to'] = selection[0][0]

            else:
                values['state_to'] = selection[sequence][0]

            if  values['state_to'] in ['done','已发布','已完成']:
                values['is_stop'] = True

            process = self.env['workflow.node'].sudo().create(values)
            if ref:
                values = {
                    'next_id': process.id,
                }
                ref.sudo().write(values)

            ref = process
            sequence = sequence + 1
        return True

class workflow_node(models.Model):
    """
    工作流
    """
    _name = "workflow.node"
    _description = "工作流节点"
    _log_access = False

    def _get_default_uuid(self):
        return str(uuid.uuid4())

    name = fields.Char(string='名称')
    value = fields.Char(string='值')
    number = fields.Char(string='流程编号', default=_get_default_uuid, index=True)
    active = fields.Boolean(default=True, string='是否有效')
    attr = fields.Selection([
        ('串签', '串签'),
        ('并签', '并签'),
        ('汇签', '汇签'),
    ], string='类型', default='串签', help="""串签、并签、汇签，也就是
    串流、并流、择流。
    假设一份文件需要A、B两个主管来审批，那么，
    串签：A签完，才轮到B来签；一般A是小领导，B是大领导；
    并签：A和B是并列的，可同时签，但必须2人都要签；一般A和B是同一层级但不同部门领导
    汇签：A和B是并列的，但只需一个签就可以了；此处A、B就是完全等价的了""")

    workflow_id = fields.Many2one('workflow', string='明细', required=True, ondelete='cascade', index=True, copy=False)
    button_name = fields.Char(string='按钮名称', default='order_confirm')
    sequence = fields.Integer(string='排序', default=10)

    node = fields.Selection([
        ('开始', '开始'),
        ('节点', '节点'),
        ('结束', '结束'),
        ('自定义', '自定义'),
    ], string='类型', default='自定义')

    type = fields.Selection([
        ('权限组', '权限组'),
        ('固定审核人', '固定审核人'),
        ('自定义', '自定义'),
    ], string='类型', default='自定义')

    state_form = fields.Char(string='从状态')
    state_to = fields.Char(string='到状态')
    state_next = fields.Char(string='下级状态', default='')
    refuse = fields.Char(string='拒绝状态', default='新建', required=True, )
    is_department = fields.Boolean(default=True, string='当前部门')
    is_company = fields.Boolean(default=True, string='当前公司')
    is_leader = fields.Boolean(default=False, string='我的领导')
    is_hide = fields.Boolean(default=True, string='隐藏选择人')
    is_stop = fields.Boolean(default=False, string='停止工作流')
    is_history = fields.Boolean(default=True, string='使用上次审核人', help='一次的选择人员')

    domain = fields.Char(string='规则', default="[(1,'=',1)]", )
    power = fields.Char(string='角色', default='', )
    parent_id = fields.Many2one('workflow.node', string='上级')
    next_id = fields.Many2one('workflow.node', string='下级')
    go_next_id = fields.Many2one('workflow.node', string='拒绝退回指定流程')
    users_ids = fields.Many2many('res.users', 'workflow_node_line_res_users_rel', 'process_id', 'user_id',
                                 string='固定审核人')
    context = fields.Text('上下文', help='用于记录上下文信息与客户端同步')
    groups_ids = fields.Many2many('res.groups', 'workflow_node_line_res_groups_rel', 'process_id', 'group_id',
                                  string='权限组')

    code_before = fields.Text('审批之前执行Python 代码')
    code_inside = fields.Text('每次执行Python 代码')
    code_after = fields.Text('结束后执行Python 代码')
    line_ids = fields.One2many('workflow.line', 'node_id', string='工作流线', copy=True, auto_join=True)

    extra = fields.Text('额外参数值')
    label = fields.Char(string='节点标签', store=True)
    x = fields.Integer(string='节点位置X', default=0)
    y = fields.Integer(string='节点位置Y', default=0)
    width = fields.Integer(string='节点宽', default=1)
    height = fields.Integer(string='节点高', default=1)
    angle = fields.Integer(string='节点旋转角度', default=0)

class workflow_line(models.Model):
    """
    工作流
    """
    _name = "workflow.line"
    _description = "工作流"
    _log_access = False

    name = fields.Char(string='名称', store=True)
    shape = fields.Selection([('edge', 'edge'),], string='属性', default='edge')
    user_id = fields.Many2one('res.users', string='用户', index=True)
    active = fields.Boolean(default=True, string='是否有效')
    node_id = fields.Many2one('workflow.node', string='工作流', ondelete='cascade', index=True, copy=False)
    # node_id = fields.Many2one('workflow.node', string='工作流', required=True, ondelete='cascade', index=True,copy=False)

    start_id = fields.Many2one('workflow.node', string='开始结点')
    end_id = fields.Many2one('workflow.node', string='结束结点')
    workflow_id = fields.Many2one('workflow', string='工作流', required=True, ondelete='cascade', index=True,copy=False)

    def _get_default_uuid(self):
        return str(uuid.uuid4())

    number = fields.Char(string='流程编号', default=_get_default_uuid)